<script setup lang="ts">
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'
import { ref, onMounted } from 'vue'

const { Color, Group, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, MeshPhongMaterial, LineSegments, Mesh, DoubleSide, WireframeGeometry, SphereGeometry } = THREE

const domEl = ref(null)

const drawSphereGeometry = () => {
  const scene = new THREE.Scene()
  scene.background = new Color( 0x444444 )

  // 相机
  const camera = new THREE.PerspectiveCamera( 75, domEl.value.offsetWidth / domEl.value.offsetHeight, 0.1, 1000 )
  camera.position.set(0, 0, 10)
  scene.add(camera)

  const renderer = new THREE.WebGLRenderer({
    antialias: true
  })
  renderer.setSize( domEl.value.offsetWidth, domEl.value.offsetHeight )
  domEl.value.appendChild( renderer.domElement )

  // 轨道
  const controls = new OrbitControls( camera, renderer.domElement )

  const updateGroupGeometry = ( mesh, geometry ) => {

    mesh.children[ 0 ].geometry.dispose()
    mesh.children[ 1 ].geometry.dispose()

    mesh.children[ 0 ].geometry = new WireframeGeometry( geometry )
    mesh.children[ 1 ].geometry = geometry

  }

  const Geometry = (mesh) => {

    const twoPi = Math.PI * 2
    const data = {
      radius: 15,
      widthSegments: 32,
      heightSegments: 16,
      phiStart: 0,
      phiLength: twoPi,
      thetaStart: 0,
      thetaLength: Math.PI
    }
    const generateGeometry = () => {
      updateGroupGeometry(mesh, new SphereGeometry(
          data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength
      ))
    }

    const gui = new GUI({ container: domEl.value, width: 310 })
    const folder = gui.addFolder( 'THREE.SphereGeometry' )

    folder.add( data, 'radius', 1, 30 ).onChange( generateGeometry )
    folder.add( data, 'widthSegments', 3, 64 ).step( 1 ).onChange( generateGeometry )
    folder.add( data, 'heightSegments', 2, 32 ).step( 1 ).onChange( generateGeometry )
    folder.add( data, 'phiStart', 0, twoPi ).onChange( generateGeometry )
    folder.add( data, 'phiLength', 0, twoPi ).onChange( generateGeometry )
    folder.add( data, 'thetaStart', 0, twoPi ).onChange( generateGeometry )
    folder.add( data, 'thetaLength', 0, twoPi ).onChange( generateGeometry )

    generateGeometry()
  }

  const geometry = new BufferGeometry()
  // geometry.setAttribute( 'position', new Float32BufferAttribute( [], 3 ) )

  const lineMaterial = new LineBasicMaterial( { color: 0xffffff, transparent: true, opacity: 0.5 } )
  const meshMaterial = new MeshPhongMaterial( { color: 0x156289, emissive: 0x072534, side: DoubleSide, flatShading: true } )


  const group = new Group()
  group.add( new LineSegments( geometry, lineMaterial ) )
  group.add( new Mesh( geometry, meshMaterial ) )
  Geometry(group)
  scene.add( group )

  function animate() {
    requestAnimationFrame( animate )
    group.rotation.x += 0.005
    group.rotation.y += 0.005
    controls.update()
    renderer.render( scene, camera )
  }
  animate()

  window.addEventListener( 'resize', function () {

    camera.aspect = domEl.value.offsetWidth / domEl.value.offsetHeight
    camera.updateProjectionMatrix()

    renderer.setSize( domEl.value.offsetWidth, domEl.value.offsetHeight )

  }, false )
}

onMounted(() => {
  drawSphereGeometry()
})

</script>

<template>
  <div ref="domEl" class="domEl-class relative w-screen h-screen "></div>
</template>

<style scoped lang="scss">
:deep(.lil-gui.root) {
  position: absolute;
  right: 0;
  top: 0;
}
</style>